<!--
 * @Descripttion: 动态表单渲染器
 * @version: 1.0
 * @Author: sakuya+tcy
 * @Date: 2024年3月22日09:26:25
 * @LastEditors:
 * @LastEditTime:
-->

<template>
    <!-- <el-skeleton v-if="renderLoading || Object.keys(form).length == 0" animated /> -->
    <el-form
      ref="formRef"
      :model="form"
      :label-width="config.labelWidth"
      :label-position="config.labelPosition"
      v-loading="loading"
      element-loading-text="Loading..."
    >
      <el-row :gutter="15">
        <slot name="content"></slot>
        <template v-for="(item, index) in config.formItems" :key="index">
          <el-col v-if="config.type == 'from'" :span="item.span || 24">
            <sc-title
              v-if="item.component == 'title'"
              :title="item.label"
            ></sc-title>
  
            <el-form-item v-else :prop="item.name">
              <template #label>
                <span
                  v-if="item.required"
                  style="color: #f56c6c; margin-right: 4px"
                  >*</span
                >
                <span style="display: inline-block">{{ item.label }}</span>
              </template>
              <!-- input -->
              <!-- && item.pattern == 'simple' -->
              <component ref="fieldRef" :is="getFieldWidget(item)" v-model="config.formItems[index]"></component>
              <template
                v-if="item.component == 'input' && item.pattern == 'simple'"
              >
                <el-input
                  v-model="form[item.name]"
                  :placeholder="item.placeholder"
                  clearable
                  :type="item.options.type"
                  :maxlength="item.options.maxlength"
                  show-word-limit
                  :size="item.size"
                  :disabled="item.disabled"
                >
                  <template v-if="item.options.append" #append>{{
                    item.options.append
                  }}</template>
                </el-input>
              </template>
              <!-- input range -->
              <!-- && item.pattern == 'complex' -->
              <template
                v-else-if="item.component == 'input' && item.pattern == 'complex'"
              >
                <el-row>
                  <el-col :span="11">
                    <!-- operatorData. -->
                    <el-input
                      v-model="form[item.name.inputVaule1]"
                      :placeholder="item.placeholder"
                      clearable
                      :maxlength="item.options.maxlength"
                      show-word-limit
                      :size="item.size"
                      :disabled="item.disabled"
                    ></el-input>
                  </el-col>
                  <el-col :span="2"
                    ><span style="margin-left: 0.5rem">-</span></el-col
                  >
                  <el-col :span="11">
                    <!-- operatorData. -->
                    <el-input
                      v-model="form[item.name.inputVaule2]"
                      :placeholder="item.placeholder"
                      clearable
                      :maxlength="item.options.maxlength"
                      show-word-limit
                      :size="item.size"
                      :disabled="item.disabled"
                    ></el-input>
                  </el-col>
                </el-row>
              </template>
              <!-- checkbox -->
              <template v-else-if="item.component == 'checkbox'">
                <template v-if="item.name">
                  <el-checkbox
                    v-model="form[item.name][_item.name]"
                    :label="_item.label"
                    v-for="(_item, _index) in item.options.items"
                    :key="_index"
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-checkbox>
                </template>
                <template v-else>
                  <el-checkbox
                    v-model="form[_item.name]"
                    :label="_item.label"
                    v-for="(_item, _index) in item.options.items"
                    :key="_index"
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-checkbox>
                </template>
              </template>
              <!-- checkboxGroup -->
              <template v-else-if="item.component == 'checkboxGroup'">
                <el-checkbox-group
                  v-model="form[item.name]"
                  :min="item.options.min"
                  :max="item.options.max"
                >
                  <el-checkbox
                    v-for="_item in item.options.items"
                    :key="_item.value"
                    :label="_item.value"
                    :size="item.size"
                    :disabled="item.disabled"
                    >{{ _item.label }}</el-checkbox
                  >
                </el-checkbox-group>
              </template>
              <!-- upload -->
              <template v-else-if="item.component == 'upload'">
                <el-col
                  v-for="(_item, _index) in item.options.items"
                  :key="_index"
                >
                  <el-form-item :prop="_item.name">
                    <sc-upload
                      v-model="form[_item.name]"
                      :title="_item.label"
                    ></sc-upload>
                  </el-form-item>
                </el-col>
              </template>
              <!-- switch -->
              <template v-else-if="item.component == 'switchv'">
                <el-switch
                  v-model="form[item.name]"
                  :size="item.size"
                  :disabled="item.disabled"
                  :active-value="item.options.activeValue"
                  :inactive-value="item.options.inactiveValue"
                />
              </template>
              <!-- select -->
              <template v-else-if="item.component == 'select'">
                <el-select
                  v-model="form[item.name]"
                  :multiple="
                    item.options.multiple ? item.options.multiple : false
                  "
                  :placeholder="item.placeholder ? item.placeholder : '请选择'"
                  clearable
                  filterable
                  collapse-tags
                  :max-collapse-tags="2"
                  :size="item.size"
                  :disabled="item.disabled"
                  :multiple-limit="item.options.limit"
                  style="width: 100%"
                  @change="handleFieldChange"
                >
                  <el-option
                    v-for="option in item.options.items"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"
                  ></el-option>
                </el-select>
              </template>
              <!--treeSelect-->
              <template v-else-if="item.component == 'treeSelect'">
                <el-tree-select
                  v-model="form[item.name]"
                  :data="item.options.items"
                  :check-strictly="item.options.checkStrictly"
                  :multiple="item.options.multiple"
                  :show-checkbox="item.options.showCheckbox"
                  collapse-tags
                  :max-collapse-tags="2"
                  clearable
                  :multiple-limit="item.options.limit"
                  :size="item.size"
                  @focus="treeSelectFocus(item)"
                  :disabled="item.disabled"
                >
                </el-tree-select>
              </template>
              <!-- cascader -->
              <template v-else-if="item.component == 'cascader'">
                <el-cascader
                  v-model="form[item.name]"
                  :options="item.options.items"
                  :props="getCascaderProps(item.options)"
                  clearable
                  collapse-tags
                  :show-all-levels="false"
                  filterable
                  :max-collapse-tags="2"
                  :size="item.size"
                  :disabled="item.disabled"
                ></el-cascader>
              </template>
  
              <!-- date -->
              <template
                v-else-if="
                  item.component == 'datePicker' && item.pattern == 'simple'
                "
              >
                <!-- :type="item.options.type"  -->
                <el-date-picker
                  v-model="form[item.name]"
                  :type="item.option.dateType"
                  :shortcuts="item.options.shortcuts"
                  :default-time="item.options.defaultTime"
                  :value-format="item.options.valueFormat"
                  :placeholder="item.placeholder || '请选择'"
                  :size="item.size"
                  :disabled="item.disabled"
                ></el-date-picker>
              </template>
              <!-- dataRange -->
              <template
                v-else-if="
                  item.component == 'datePicker' && item.pattern == 'complex'
                "
              >
                <el-row>
                  <el-col :span="4">
                    <el-select
                      v-model="form[item.name.operator]"
                      :placeholder="item.placeholder || '请选择'"
                      filterable
                      style="width: 100%"
                      @change="(value) => dataChange(value, item)"
                    >
                      <el-option
                        v-for="option in item.operatorData"
                        :key="option.value"
                        :label="option.label"
                        :value="option.value"
                        :size="item.size"
                        :disabled="item.disabled"
                      ></el-option>
                    </el-select>
                  </el-col>
                  <el-col :span="8" style="margin-left: 0.25rem">
                    <el-date-picker
                      v-model="form[item.name.startValue]"
                      :type="date"
                      :shortcuts="item.options.shortcuts"
                      value-format="YYYY-MM-DD"
                      :placeholder="item.placeholder || '请选择'"
                      :size="item.size"
                      :disabled="item.disabled"
                    ></el-date-picker>
                  </el-col>
                  <el-col :span="1"
                    ><span style="margin-left: 0.5rem"> - </span></el-col
                  >
                  <el-col :span="8">
                    <el-date-picker
                      v-model="form[item.name.endValue]"
                      :type="date"
                      :shortcuts="item.options.shortcuts"
                      value-format="YYYY-MM-DD"
                      :placeholder="item.placeholder || '请选择'"
                      :size="item.size"
                      :disabled="item.disabled"
                    ></el-date-picker>
                  </el-col>
                </el-row>
              </template>
              <!-- number -->
              <template
                v-else-if="
                  item.component == 'inputNumber' && item.pattern == 'simple'
                "
              >
                <el-input-number
                  v-model="form[item.name]"
                  controls-position="right"
                  :size="item.size"
                  :disabled="item.disabled"
                  :min="item.options.min"
                  :max="item.options.max"
                  :step="item.options.step"
                  :precision="item.options.precision"
                ></el-input-number>
              </template>
              <!-- number range -->
              <template
                v-else-if="
                  item.component == 'inputNumber' && item.pattern == 'complex'
                "
              >
                <el-col :xs="14" :sm="6" :md="6">
                  <el-select
                    v-model="form[item.name.operator]"
                    :placeholder="item.placeholder || '请选择'"
                    @change="changeInputNumber"
                    clearable
                    filterable
                    style="width: 100%"
                  >
                    <el-option
                      v-for="option in item.operatorData"
                      :key="option.value"
                      :label="option.label"
                      :value="option.value"
                      :size="item.size"
                      :disabled="item.disabled"
                    ></el-option>
                  </el-select>
                </el-col>
                <el-col :xs="24" :sm="10" :md="8">
                  <el-input-number
                    v-model="form[item.name.startValue]"
                    controls-position="right"
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-input-number>
                </el-col>
                <el-col :xs="24" :sm="10" :md="2" v-if="isShowEndInputNumber"
                  ><span> 至 </span></el-col
                >
                <el-col :xs="24" :sm="10" :md="8" v-if="isShowEndInputNumber">
                  <el-input-number
                    v-model="form[item.name.endValue]"
                    controls-position="right"
                    :size="item.size"
                    :disabled="item.disabled"
                  ></el-input-number>
                </el-col>
              </template>
              <!-- radio -->
              <template v-else-if="item.component == 'radio'">
                <el-radio-group v-model="form[item.name]">
                  <el-radio
                    v-for="_item in item.options.items"
                    :key="_item.value"
                    :label="_item.value"
                    >{{ _item.label }}</el-radio
                  >
                </el-radio-group>
              </template>
              <!-- color -->
              <template v-else-if="item.component == 'color'">
                <el-color-picker v-model="form[item.name]" />
              </template>
              <!-- rate -->
              <template v-else-if="item.component == 'rate'">
                <el-rate
                  style="margin-top: 6px"
                  v-model="form[item.name]"
                  :allow-half="item.options.allowHalf"
                ></el-rate>
              </template>
              <!-- slider -->
              <template v-else-if="item.component == 'slider'">
                <el-slider
                  v-model="form[item.name]"
                  :marks="item.options.marks"
                ></el-slider>
              </template>
              <!-- tableselect -->
              <template v-else-if="item.component == 'complexInputBox'">
                <tableselect-render
                  v-model="form[item.name]"
                  :item="item"
                ></tableselect-render>
              </template>
              <!-- editor -->
              <template v-else-if="item.component == 'editor'">
                <sc-editor
                  v-model="form[item.name]"
                  placeholder="请输入"
                  :height="400"
                ></sc-editor>
              </template>
              <!--codeEditor-->
              <template v-else-if="item.component == 'codeEditor'">
                <ts-code-editor
                  style="width: 100%"
                  v-model="form[item.name]"
                  :height="item.options.height"
                ></ts-code-editor>
              </template>
              <!-- noComponent -->
              <template v-else>
                <el-tag type="danger"
                  >[{{ item.component }}] Component not found</el-tag
                >
              </template>
              <div v-if="item.message" class="el-form-item-msg">
                {{ item.message }}
              </div>
            </el-form-item>
          </el-col>
        </template>
        <slot name="footer"></slot>
      </el-row>
    </el-form>
  </template>
  
  <script setup>
  import http from "@/utils/request";
  import $time from "@/utils/time";
  import Api from "@/api/model/system";
  import tsCodeEditor from "@/components/scCodeEditor/index.vue";
  import {
    defineAsyncComponent,
    onMounted,
    watch,
    ref,
    defineModel,
    computed,
  } from "vue";
  const tableselectRender = defineAsyncComponent(() =>
    import("./items/inputSelect")
  );
  const scEditor = defineAsyncComponent(() => import("@/components/scEditor"));
  const props = defineProps({
    config: { type: Object, default: () => {} },
    loading: { type: Boolean, default: false },
    fileName: { type: String, default: "" },
  });
  const form = defineModel();
  const formRef = ref(null);
  const renderLoading = ref(false);
  const isShowEndInputNumber = ref(true);
  watch(
    () => props.config,
    () => {
      if (hasConfig.value) {
        render();
      }
    }
  );
  const hasConfig = computed(() => {
    return Object.keys(props.config).length > 0;
  });
  onMounted(() => {
    if (hasConfig.value) {
      render();
    }
  });
  const render = () => {
    props.config.formItems.forEach((item) => {
      if (item.component == "checkbox") {
        if (item.name) {
          const value = {};
          item.options.items.forEach((option) => {
            value[option.name] = option.value;
          });
          form.value[item.name] = value;
        } else {
          item.options.items.forEach((option) => {
            form.value[option.name] = option.value;
          });
        }
      } else if (item.component == "upload") {
        if (item.name) {
          const value = {};
          item.options.items.forEach((option) => {
            value[option.name] = option.value;
          });
          form.value[item.name] = value;
        } else {
          item.options.items.forEach((option) => {
            form.value[option.name] = option.value;
          });
        }
      } else if (item.component == "datePicker" && item.pattern == "complex") {
        form.value[item.name.operator] = item.value.operator;
        form.value[item.name.startValue] = item.value.startValue;
        form.value[item.name.endValue] = item.value.endValue;
      } else if (item.component == "inputNumber" && item.pattern == "complex") {
        form.value[item.name.operator] = item.value.operator;
        form.value[item.name.startValue] = item.value.startValue;
        form.value[item.name.endValue] = item.value.endValue;
      } else {
        if (form.value[item.name] == undefined) {
          form.value[item.name] = item.value;
        }
      }
    });
    getData();
  };
  //选择项远程数据加载
  const getData = () => {
    renderLoading.value = true;
    var remoteData = [];
    props.config.formItems.forEach((item) => {
      if (item.options && item.options.remote) {
        var req = http
          .get(item.options.remote.api, item.options.remote.data)
          .then((res) => {
            item.options.items = res.data;
          });
        remoteData.push(req);
      }
    });
    Promise.all(remoteData).then(() => {
      renderLoading.value = false;
    });
  };
  const treeSelectFocus = async (item) => {
    if (item.options.items.length === 0) {
      let params = {
        fileName: item.options.dataset.fileName,
      };
      let res = await Api.select.query.post(params);
      if (res.code == "200") {
        item.options.items = res.reportData;
      }
    }
  };
  const validate = (valid, obj) => {
    return formRef.value.validate(valid, obj);
  };
  const dataChange = (val, item) => {
    if (
      item.component == "datePicker" &&
      item.pattern == "complex" &&
      val !== "between"
    ) {
      form.value[item.name.startValue] = $time.getDateRange(val)[0];
      form.value[item.name.endValue] = $time.getDateRange(val)[1];
    } else if (val == "between") {
      form.value[item.name.startValue] = "";
      form.value[item.name.endValue] = "";
    }
  };
  const changeInputNumber = (val) => {
    if (val == "between") {
      isShowEndInputNumber.value = true;
    } else {
      isShowEndInputNumber.value = false;
    }
  };
  //级联选择器配置
  const getCascaderProps = (val) => {
    return {
      multiple: val.multiple,
      checkStrictly: val.checkStrictly,
    };
  };
  defineExpose({ validate });
  </script>
  <style></style>